package com.chenfan.common.extension.validation;

import org.apache.commons.lang3.ArrayUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.time.DateUtils;

import javax.validation.Constraint;
import javax.validation.ConstraintValidator;
import javax.validation.ConstraintValidatorContext;
import javax.validation.Payload;
import java.lang.annotation.*;
import java.text.ParseException;
import java.util.Locale;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.regex.Pattern;

/**
 * 日期时间范围校验注解，可作用于LocalDateTime or 字符串型年月日时分秒（格式可通过pattern属性指定）
 * @author wulg
 * @date 2023/4/19
 */
@Target({ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Constraint(validatedBy = DateTimeString.DateTimeStringValidator.class)
public @interface DateTimeString {

    /**
     * 用于校验日期格式
     * @return
     */
    String regexp() default "^((\\d{4}(-)\\d{2}(-)\\d{2})|(\\d{4}(/)\\d{2}(/)\\d{2}))((\\s)\\d{2}:\\d{2}:\\d{2})?$";

    /**
     * 用于解析日期内容是否非法
     */
    String[] parsePatterns() default {"yyyy-MM-dd HH:mm:ss", "yyyy-MM-dd", "yyyy/MM/dd HH:mm:ss", "yyyy/MM/dd"};

    /**
     * 是否强制解析
     * @return
     */
    boolean strictlyParse() default true;

    /**
     * 错误提示
     */
    String message() default "时间格式或内容有误";

    /**
     * 用于分组校验
     */
    Class<?>[] groups() default {};

    /**
     *
     * @return
     */
    Class<? extends Payload>[] payload() default {};

    /**
     *
     */
    class DateTimeStringValidator implements ConstraintValidator<DateTimeString, String> {

        private DateTimeString dateTimeString;

        private static Map<String, Pattern> regexpMap = new ConcurrentHashMap<>(4);

        @Override
        public void initialize(DateTimeString dateTimeString) {
            this.dateTimeString = dateTimeString;
            if(StringUtils.isNotBlank(dateTimeString.regexp())) {
                if(!regexpMap.containsKey(dateTimeString.regexp())) {
                    regexpMap.put(dateTimeString.regexp(), Pattern.compile(dateTimeString.regexp(), Pattern.MULTILINE));
                }
            }
        }

        @Override
        public boolean isValid(String value, ConstraintValidatorContext context) {
            if(StringUtils.isBlank(value)) {
                return true;
            }
            //校验日期格式
            if(StringUtils.isNotBlank(dateTimeString.regexp())) {
                Pattern pattern = regexpMap.get(dateTimeString.regexp());
                if(!pattern.matcher(value).matches()) {
                    return false;
                }
            }
            //校验日期内容
            if(ArrayUtils.isNotEmpty(dateTimeString.parsePatterns())) {
                try {
                    if(dateTimeString.strictlyParse()) {
                        DateUtils.parseDateStrictly(value, Locale.CHINA, dateTimeString.parsePatterns());
                    } else {
                        DateUtils.parseDate(value, Locale.CHINA, dateTimeString.parsePatterns());
                    }
                    return true;
                } catch (ParseException e) {
                    return false;
                }
            }
            return true;
        }
    }
}